<?php
class TestResults {
  
  private $testResults;
  
  /**
   * @param string $class
   * @param string $method
   * @return TestResult
   */
  function getResult($class,$method) {
    $key = $class.'::'.$method;
    return $this->testResults[$key];  
  }
  
  function hasResult($class,$method) {
    $key = $class.'::'.$method;
    return array_key_exists($key,$this->testResults);
  }
  
  function getResults() {
    return $this->testResults;
  }
  
  static function processNode($xml) {
    $results = array();
    foreach ($xml->testsuite as $node) {
      $results = array_merge($results,self::processTestSuite($node));
    }
    return $results;
  }
  
  static function processTestSuite($node) {
    $results = array();
    $at = (array)$node->attributes();
    $at = $at['@attributes'];
    foreach($node->testcase as $node) {
      $result = self::processTestCase($node);
      $results[$result->getClass().'::'.$result->getName()] = $result;
    }
    foreach ($node->testsuite as $node) {
      $results = array_merge($results,self::processTestSuite($node));
    }
    return $results;
  }
  
  static function processTestCase($node) {
    $at = (array)$node->attributes();
    $at = $at['@attributes'];
    $result = new TestResult(
      $at['class'],
      $at['name'],
      $at
    );
    foreach($node->error as $error) {
      $at = (array)$error->attributes();
      $at = $at['@attributes'];
      $result->setError($at['type'],(string)$error,$at);
      if($at['type'] == 'PHPUnit_Framework_IncompleteTestError') {
        $result->setResult(TestResult::INCOMPLETE);  
      }
      else {
        $result->setResult(TestResult::ERROR);
      }
    }
    foreach($node->failure as $failure) {
      $at = (array)$failure->attributes();
      $at = $at['@attributes'];
      $result->setError($at['type'],(string)$failure,$at);
      $result->setResult(TestResult::FAILURE);
    }
    if(!$result->hasResult()) {
      $result->setResult(TestResult::SUCCESS);
    }
    return $result;
  }
  
  /**
   * @param string $xmlFile path to the file.
   * Depending on the structure of the xml this parse does not recognize the tests.
   * It might have something with using $xml->testsuite[0] on the first foreach loop 
   * @todo improve the parse for vrious xml nesting structures. 
   * @return TestResults may return false if no results are found. 
   */
  static function importResultXmlFile($xmlFile) {
    if(!file_exists($xmlFile)) {
      throw new InvalidArgumentException('Xml file not found: '.$xmlFile);
    }
    $xml = simplexml_load_file($xmlFile);
    if(!$xml) {
      trigger_error('Error importing the '.$xmlFile.' file!');
    }
    //echo "<pre>";
    //print_r($xml);
    //die();
    $results = self::processNode($xml);
    
    if(count($results)) {
      return new TestResults($results);
    }
    else {
      return false;
    }
  }
  
  
  
  function __construct($testResults) {
    $this->testResults = $testResults;
  }
  
}